package com.java.simple.study.juc.p7;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

/**
 * @author zhoujunlin
 * @date 2022年08月07日 21:48
 * @desc
 */
@Slf4j(topic = "c.TestForkJoin")
public class TestForkJoin {

    public static void main(String[] args) {
        ForkJoinPool forkJoinPool = new ForkJoinPool(4);
        //log.debug(forkJoinPool.invoke(new AddTask1(5)) + "");
        log.debug(forkJoinPool.invoke(new AddTask3(1, 5)) + "");
    }

}

@Slf4j(topic = "c.AddTask1")
class AddTask1 extends RecursiveTask<Integer> {
    int n;

    public AddTask1(int n) {
        this.n = n;
    }

    @Override
    public String toString() {
        return "{" + n + "}";
    }

    @Override
    protected Integer compute() {
        if (n == 1) {
            // 如果 n 已经为 1，可以求得结果了
            log.debug("join() -> {}", 1);
            return n;
        }
        // 将任务进行拆分(fork)
        AddTask1 task1 = new AddTask1(n - 1);
        task1.fork();
        log.debug("fork() -> {}+{}", n, task1);
        // 合并(join)结果
        int result = n + task1.join();
        log.debug("join() -> {}+{}={}", n, task1, result);
        return result;
    }
}

@Slf4j(topic = "c.AddTask3")
class AddTask3 extends RecursiveTask<Integer> {
    int begin;
    int end;

    public AddTask3(int begin, int end) {
        this.begin = begin;
        this.end = end;
    }

    @Override
    public String toString() {
        return "{" + begin + "," + end + "}";
    }

    @Override
    protected Integer compute() {
        if (begin == end) {
            log.debug("join() -> {}", begin);
            return begin;
        }
        if (end - begin == 1) {
            log.debug("join() -> {}+{}={}", begin, end, end + begin);
            return end + begin;
        }
        int mid = (end + begin) / 2;
        // 将任务进行拆分(fork)
        AddTask3 task1 = new AddTask3(begin, mid);
        task1.fork();
        AddTask3 task2 = new AddTask3(mid + 1, end);
        task2.fork();
        log.debug("fork() -> {}+{}", task1, task2);
        // 合并(join)结果
        int result = task1.join() + task2.join();
        log.debug("join() -> {}+{}={}", task1, task2, result);
        return result;
    }
}

